#include "OverUnderFrequency.h"
#include "../function_interface.h"
#include "../types.h"
#include <stdio.h>
#include "../logInterface.h"
#include "../global_variable.h"


#if 1

typedef struct {
    int   olThrEnterFreq_0p01hz;//进入判定阈值
    int   olThrEnterTime_1s;//进入判定时间
    int   olThrExitFreq_0p01hz;//退出判定阈值
    int   olThrExitTime_1s;//退出判定时间
}ouFreqConfType;//过/欠频配置类型


typedef struct {
    int      olEnterTime_1s;//当前已进入判定阈值的时间,该值超过olThrEnterTime_1s判定为该级过/欠频
    int      olExitTime_1s;//当前已退出判定阈值的时间,该值超过olThrExitTime_1s判定为脱离该级过/欠频
    uint32_t olKeepTime_1s;//该级过/欠频已持续的时间(保持该级过/欠频不变的情况下).
    uint32_t olTotalTime_1s;//该级过/欠频总工作的时间.
    uint32_t olOnTime_1s;//系统功率级别为该级过/欠频已持续的时间().
}ouFreqRealtimeInfoType;



static ouFreqConfType ouFreqConfig[OUFREQ_LEVEL_QTY];

static ouFreqRealtimeInfoType ouFreqRealtimeInfo[OUFREQ_LEVEL_QTY];


void ouFreq_GetFreqThreshold(void)
//获取3级过/欠压的阈值和判定时间.
{
    int levelIdx=0;
    float value;
    ouFreqConfType* pFreqConfig = ouFreqConfig;
    for(levelIdx=0;levelIdx<OUFREQ_LEVEL_QTY;levelIdx++)
    {
        switch(levelIdx)
        {
            case UNDERFREQ_LEVEL_1:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UF_THR,&value);
                pFreqConfig[levelIdx].olThrEnterFreq_0p01hz = (int)(value*100);

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UF_TIME,&value);
                pFreqConfig[levelIdx].olThrEnterTime_1s     = (int)(value);

                pFreqConfig[levelIdx].olThrExitFreq_0p01hz  = pFreqConfig[levelIdx].olThrEnterFreq_0p01hz;
                pFreqConfig[levelIdx].olThrExitTime_1s      = 10;
            }break;
            case OVERFREQ_LEVEL_1:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OF_THR,&value);
                pFreqConfig[levelIdx].olThrEnterFreq_0p01hz = (int)(value*100);

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OF_TIME,&value);
                pFreqConfig[levelIdx].olThrEnterTime_1s     = (int)(value);

                pFreqConfig[levelIdx].olThrExitFreq_0p01hz  = pFreqConfig[levelIdx].olThrEnterFreq_0p01hz;
                pFreqConfig[levelIdx].olThrExitTime_1s      = 10;
            }break;
        }
    }
}



void OverUnderFreq_Loop(void* pPara)
//主要用于判别一级过/欠频
{

    int index=0;
    int currFreq_0p01hz;/* 当前频率 */
    int enterThrFreq_0p01hz,exitThrFreq_0p01hz;
    int enterThrTime_1s/*进入该级的判定时间阈值*/,exitThrTime_1s/*退出该级的判定时间阈值*/;
    fpagDataFsm_t fsm;
    float freq_1hz;
    uint16_t arm3LSwitch;

    const ouFreqConfType* pOuFreqConfig = ouFreqConfig;

    ouFreqRealtimeInfoType* pOUFreqRealtimeInfo = ouFreqRealtimeInfo;

    if(FUNCINF_ERR_NONE == FuncInf_GetFsm(FUNCINF_FSM_TYPE_THIS_TIME,&fsm))
    {
        if((fsm == FUNCINF_FSM_IDLE) || (fsm == FUNCINF_FSM_FAULT) || (fsm == FUNCINF_FSM_STOP))
        //关机后将过频计时时间清零, 故障标志位置1
        {
            for(index=0;index<OUFREQ_LEVEL_QTY;index++)
            {
                pOUFreqRealtimeInfo[index].olKeepTime_1s = 0;
            }

            if((fsm == FUNCINF_FSM_IDLE) || (fsm == FUNCINF_FSM_STOP))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_OF, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_UF, 0);
            }
            return;
        }
    }
    else
    {
        return;
    }

    //ARM三级保护策略使能后才检测过欠频
    if(FUNCINF_ERR_NONE == FuncInf_GetStrategySwitch(FUNCINF_STRTG_SWITCH_TYPE_ARM_3L_PRTCT,&arm3LSwitch))
    {
        if(arm3LSwitch == 0)
        //未使能三级保护, 故障标志位置1
        {
            GlobalVariable_SetUint8(GV_UINT8_3L_OF, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_UF, 0);
            return;
        }
    }

    FuncInf_GetFrequency(NULL,&freq_1hz);
    currFreq_0p01hz = (int)(freq_1hz*100);
    if(pPara)
    {
        printf("Module:OverUnderFrequency detect Freq:%d(0.01hz)\n",currFreq_0p01hz);
    }

    ouFreq_GetFreqThreshold();
    for(index=0;index<OUFREQ_LEVEL_QTY;index++)
    {
        //阈值
        enterThrFreq_0p01hz = pOuFreqConfig[index].olThrEnterFreq_0p01hz;
        exitThrFreq_0p01hz  = pOuFreqConfig[index].olThrExitFreq_0p01hz;

        //时间阈值
        enterThrTime_1s = pOuFreqConfig[index].olThrEnterTime_1s;
        exitThrTime_1s = pOuFreqConfig[index].olThrExitTime_1s;
        
        switch(index)
        {
            case UNDERFREQ_LEVEL_1:
            {
                if(currFreq_0p01hz < enterThrFreq_0p01hz)
                //满足该级进入判定
                {
                    if(pOUFreqRealtimeInfo[index].olEnterTime_1s++ >= enterThrTime_1s)
                    {
                        pOUFreqRealtimeInfo[index].olKeepTime_1s++;//本次该级欠频持续的时间
                        pOUFreqRealtimeInfo[index].olTotalTime_1s++;//自arm启动以来该级欠频总共的时间
                    }
                }
                else
                {
                    pOUFreqRealtimeInfo[index].olEnterTime_1s = 0;
                }
                
                if(currFreq_0p01hz >= exitThrFreq_0p01hz)
                //满足该级退出判定
                {
                    if(pOUFreqRealtimeInfo[index].olExitTime_1s++ >= exitThrTime_1s)
                    {
                        pOUFreqRealtimeInfo[index].olKeepTime_1s = 0;
                    }
                }
                else
                {
                    pOUFreqRealtimeInfo[index].olExitTime_1s = 0;
                }
                
            }break;
            case OVERFREQ_LEVEL_1 :
            {
                if(currFreq_0p01hz > enterThrFreq_0p01hz)
                //满足该级进入判定
                {
                    if(pOUFreqRealtimeInfo[index].olEnterTime_1s++ >= enterThrTime_1s)
                    {
                        pOUFreqRealtimeInfo[index].olKeepTime_1s++;//本次该级过频持续的时间
                        pOUFreqRealtimeInfo[index].olTotalTime_1s++;//自arm启动以来该级过频总共的时间
                    }
                }
                else
                {
                    pOUFreqRealtimeInfo[index].olEnterTime_1s = 0;
                }
                
                if(currFreq_0p01hz <= exitThrFreq_0p01hz)
                //满足该级退出判定
                {
                    if(pOUFreqRealtimeInfo[index].olExitTime_1s++ >= exitThrTime_1s)
                    {
                        pOUFreqRealtimeInfo[index].olKeepTime_1s = 0;
                    }
                }
                else
                {
                    pOUFreqRealtimeInfo[index].olExitTime_1s = 0;
                }
                
            }break;
        }

#if 1 //我们只关注1级过欠/频(上位机点表定义为3级过欠频),其它级别的由FPGA自己处理
        if(pOUFreqRealtimeInfo[index].olKeepTime_1s == 1)
        //1级过/欠频
        {
            if((OVERFREQ_LEVEL_1==index))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_OF, 1);
                printf("Module:OVERFREQ happen currFreq_0p01hz:%d(0.1Hz)\n",currFreq_0p01hz);
            }
            if((UNDERFREQ_LEVEL_1==index))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_UF, 1);
                printf("Module:UNDERFREQ happen currFreq_0p01hz:%d(0.1Hz)\n",currFreq_0p01hz);
            }
        }
        else if(pOUFreqRealtimeInfo[index].olKeepTime_1s == 0)
        //1级过/欠频恢复
        {
            if((OVERFREQ_LEVEL_1==index))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_OF, 0);
            }
            if((UNDERFREQ_LEVEL_1==index))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_UF, 0);
            }
        }
#endif

    }
}

#if 0
int OverUnderFreq_Get(int level)
{
    ouFreqRealtimeInfoType* pOUFreqRealtimeInfo = ouFreqRealtimeInfo;
    if((OUFREQ_LEVEL_NONE<level)&&(level<OUFREQ_LEVEL_QTY))
    {
        return (0 != pOUFreqRealtimeInfo[level].olKeepTime_1s);
    }
}
#endif

#endif

